﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Drawing;
using System.Windows.Forms;

    /// <summary>
    /// Questa classe incapsula un messaggio, il messaggio è un entità non modificabile dopo la sua creazione.
    /// </summary>
    [Serializable]
    public class Messaggio
    {
        #region Variabili

        #region Chat
        private string nome; // nome di chi manda il messaggio  
        private string msg; // stringa del messaggio 
        private string password; // stringa della password
        private bool passwordset = false; // indica se la password è presente
        #endregion

        #region Frame
        private Bitmap frame; // l'immagine da inviare
        private bool isframe = false; // se è una immagine
        private bool ispart = false; //  se è completa
        private Rectangle rect; // la porzione di schermo dell'immagine
        private Point mouse; // la posizione del mouse
       
        #endregion

        #region ClipBoard

        private bool isAvailable = false; // quando nel server è presente un oggetto della clipboard
        private bool downloadClipboard = false; // quando il client vuole fare il download della clipboard
        private Object[] data_object;// elemento della clipboard nei vari formati
        private string[] formati; // tutti i formati in cui è memorizzato
        private bool isclipboardObject = false;
        private string nome_file; 
        #endregion
        
        #endregion

        #region Costruttori
        private Messaggio() { }
        public Messaggio(string nome, string password, string msg)
        {
            this.msg = msg;
            this.nome = nome;
            this.password = password;
            passwordset = true;
        }
        public Messaggio(string nome, string msg)
        {
            this.msg = msg;
            this.nome = nome;
            this.password = "";
        }
        public Messaggio(Bitmap frame, Point mouse)
        {      
            this.frame = new Bitmap(frame);
            this.isframe = true;
            this.mouse = mouse;
        }
        public Messaggio(Bitmap m2, Rectangle r, Point mouse)
        {
            // TODO: Complete member initialization
            this.frame = new Bitmap(m2);
            this.rect = r;
            this.isframe = true;
            this.ispart = true;
            this.mouse = mouse;
        }
        public Messaggio(IDataObject oggetto_clipboard)
        {
            formati = oggetto_clipboard.GetFormats();
            data_object = new Object[formati.Length];

            if (formati.Contains(DataFormats.FileDrop)) // l'utente ha condiviso un file 
            {
                
                string[] name = (string[]) oggetto_clipboard.GetData(DataFormats.FileDrop);
                Stream fs = File.Open(name[0], FileMode.Open, FileAccess.Read, FileShare.Read);
                if (fs.Length >= 25 * 1024 * 1024)
                {
                    throw new FileTooBigException();
                }
                int ultima_occorrenza = name[0].LastIndexOf("\\");
                this.nome_file = name[0].Substring(ultima_occorrenza + 1);
                this.data_object = new Object[1];
                byte[] buffer = new byte[fs.Length];
                fs.Read(buffer, 0, (int)fs.Length);
                this.data_object[0] = buffer;
                fs.Close();
                this.formati = new string[1];
                this.formati[0] = "file";
            }
            else
            {
                int i = 0;
                foreach (string formato in formati)
                    this.data_object[i++] = oggetto_clipboard.GetData(formato);
            }
            this.isclipboardObject = true;
        }
        public Messaggio(string[] formati, Object[] data)
        {
            this.formati = formati;
            this.data_object = data;
        }
        #endregion

        #region Proprietà
        public string Nome { get { return this.nome; } }
        public string Password { get { return this.password; } }
        public string Text { get { return this.msg; } }
        public bool PasswordSettata { get { return this.passwordset; } }
        public Bitmap Frame { get { return this.frame; } }
        public bool isFrame { get { return this.isframe; } }
        public bool isPart { get { return this.ispart; } }
        public Rectangle Part { get { return this.rect;} }
        public Point MousePos { get { return this.mouse; } }
        public bool isClipboardAvailable {get {return isAvailable;}}
        public bool DownloadClipboard { get { return this.downloadClipboard; } }
        public bool isClipboardObject { get { return this.isclipboardObject; } }
        public string[] FormatiClipboard { get { return this.formati; } }
        public Object[] OggettiClipboard { get { return this.data_object; } }
        public string FileName { get { return this.nome_file; } }
        #endregion

        public static Messaggio ClipboardAvailable()
        {
            Messaggio m = new Messaggio();
            m.isAvailable = true;
            return m;
        }
        public static Messaggio DownloadClipBoardMessage(string nome) {
            Messaggio m = new Messaggio();
            m.downloadClipboard = true;
            m.nome = nome;
            return m;
        }

        
        /// <summary>
        /// Da classe messaggio ad array di byte 
        /// </summary>
        /// <param name="m">L'istanza del messaggio da serializzare</param>
        /// <returns></returns>
        public static byte[] serializza(Messaggio m)
        {
            BinaryFormatter bin = new BinaryFormatter();
            MemoryStream mem = new MemoryStream();
            bin.Serialize(mem, m);
            return mem.GetBuffer();

        }
        /// <summary>
        /// Da array di byte a instanza della classe messaggio
        /// </summary>
        /// <param name="arrBytes"> l'array di byte da deserializzare</param>
        /// <returns></returns>
        public static Messaggio deserializza(byte[] arrBytes)
        {
            try
            {
               
                BinaryFormatter bin = new BinaryFormatter();
                MemoryStream mem = new MemoryStream();
                mem.Write(arrBytes, 0, arrBytes.Length);
                mem.Seek(0, 0);
                Object m =  (Object)bin.Deserialize(mem);
                Messaggio k = (Messaggio) m;
                return k;
                 
            }
            catch (SerializationException)
            {
                return null;
            }
        }



    
    }

